package models

import (
	"classmates/tool"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"strings"
	"time"

	"github.com/beego/beego/v2/client/orm"
	beego "github.com/beego/beego/v2/server/web"
)

type Homework struct {
	Id          int       `orm:"column(id);auto"`
	StudentID   int       `orm:"column(student_id);null"`
	StudentSN   string    `orm:"column(student_sn);null"`
	Score       int       `orm:"column(score);null"`
	CreateTime  time.Time `orm:"column(createTime);null"`
	Homework    string    `orm:"column(homework);null"`
	IP          string    `orm:"column(IP);null"`
	StudentName string    `orm:"column(student_name);null"`
}

func (t *Homework) TableName() string {
	return "homework"
}

func init() {
	orm.RegisterModel(new(Homework))
}

func CheckHomeWork(no, save int) {
	ip := "172.14.1.%d"
	o := orm.NewOrm()
	number, _ := beego.AppConfig.Int("scanip")
	client := &http.Client{
		Timeout: time.Duration(rand.Intn(1000)+1000) * time.Millisecond,
	}
	for k := 1; ; k++ {
		fmt.Printf("扫描第%d轮，----------------------------  \n", k)

		for i := number; i < 80; i++ {
			var homework Homework
			apiAddr := fmt.Sprintf(ip, i)
			homework.IP = apiAddr
			var err error

			for _, classmate := range AllClassMates {
				if classmate.IP == apiAddr {
					homework.StudentSN = classmate.Sn
					homework.StudentID = classmate.Id
					homework.StudentName = classmate.Name
					break
				}
			}
			time.Sleep(time.Second)
			fmt.Printf("扫描IP:%+15s上的作业：  \n", homework.IP)

			startTime := time.Now()

			switch no {
			case 1:
				err = homework1(apiAddr, client, &homework)
			case 2:

				err = homework2(apiAddr, client, &homework)
			case 3:
				err = homework3(apiAddr, client, &homework)
			case 4:
				err = homework4(apiAddr, client, &homework)
			}
			if err != nil {
				fmt.Printf("检查异常:%v \n\n", err.Error())
				continue
			}
			fmt.Printf(" 		用时：%+10v ", time.Since(startTime).String())
			homework.CreateTime = time.Now()

			if save > 0 {
				_, err = o.Insert(&homework)
				if err != nil {
					fmt.Printf("数据库写入出错，错误是:%s  \n", err.Error())
					continue
				}
			}
			fmt.Printf("  得分%+5d  \n", homework.Score)
			fmt.Println("")
			// if homework.Score > 80 {
			// 	fmt.Printf(" 姓名: %s  ", AllClassMates[homework.StudentSN].Name)
			// }
			//fmt.Printf("内容:%v  \n", homework.Homework)
		}
	}
}

func homework1(apiAddr string, client *http.Client, homework *Homework) error {
	//检查
	req, _ := http.NewRequest("GET", "http://"+apiAddr, nil)

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		homework.Homework += err.Error() + "-----"

	} else {
		// 读取响应内容
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += err.Error() + "-----"
		}
		nameZuoye := string(body)
		if strings.Contains(nameZuoye, homework.StudentName) {
			homework.Score += 10
		}
		homework.Homework = nameZuoye + "-----"
	}
	//检查加法
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/add?a=96&b=4", nil)

	// 发送请求
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += err.Error() + "-----"
		return err
	} else {
		// 读取响应内容
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += err.Error() + "-----"
			return err
		}
		nameZuoye := string(body)
		if strings.Contains(nameZuoye, "100") {
			homework.Score += 30
		}
		homework.Homework += nameZuoye + "-----"
	}
	// 检查bmi
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/bmi?weight=75&height=1.75", nil)

	// 发送请求
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += err.Error() + "-----"
		return err
	} else {

		// 读取响应内容
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += err.Error() + "-----"

		}
		nameZuoye := string(body)
		if len(nameZuoye) > 1 {
			homework.Score += 60
		}
		homework.Homework += nameZuoye + "-----"

	}

	return nil
}

func homework2(apiAddr string, client *http.Client, homework *Homework) error {
	//检查加法
	req, _ := http.NewRequest("GET", "http://"+apiAddr+"/api/chanAdd?a=1234", nil)

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		homework.Homework += (" 接口访问失败,错误是:" + err.Error())
		return err
	} else {
		// 读取响应内容
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		nameZuoye := string(body)
		if strings.Contains(nameZuoye, "761995") {
			homework.Score += 100
		} else {
			fmt.Printf(" 得到的值是：%v  , 正确的值应该是%v  \n", nameZuoye, 761995)
		}
		homework.Homework += nameZuoye + "-----"
	}
	return nil
}

func homework3(apiAddr string, client *http.Client, homework *Homework) error {
	//检查加法
	req, _ := http.NewRequest("GET", "http://"+apiAddr+"/api/append?a=日本&b=新西兰&c=澳大利亚", nil)

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		homework.Homework += (" 接口访问失败,错误是:" + err.Error())
		return err
	} else {
		// 读取响应内容
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		nameZuoye := string(body)
		if strings.Contains(nameZuoye, "日本") {
			homework.Score += 34
		}
		if strings.Contains(nameZuoye, "新西兰") {
			homework.Score += 33
		}
		if strings.Contains(nameZuoye, "澳大利亚") {
			homework.Score += 33
		}
		homework.Homework += nameZuoye + "-----"
	}
	return nil
}

// 第四次作业检查
func homework4(apiAddr string, client *http.Client, homework *Homework) error {

	//首先先执行清空数据库命令
	req, _ := http.NewRequest("GET", "http://"+apiAddr+"/v1/clear", nil)
	_, err := client.Do(req)
	if err != nil {
		homework.Homework += (" 清空数据库接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 清空数据库接口访问失败")
	}

	//1.添加记录,返回ok或者添加成功
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/v1/person/add?name="+
		tool.First_classmate+"&sex="+"男&age=20&other=重庆三峡职业学院", nil)
	resp, err := client.Do(req)
	if err != nil {
		homework.Homework += (" 添加寝室人员接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 接口访问失败！")

	} else {
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		//返回的数据是切片字节，转成字符串进行判断
		nameZuoye := string(body)
		//判断返回的字段是否有ok或者添加成功的字段值
		if strings.Contains(nameZuoye, "ok") || strings.Contains(nameZuoye, "添加成功") ||
			strings.Contains(nameZuoye, "插入成功") || strings.Contains(nameZuoye, "成功") {
			homework.Score += 10
			fmt.Println("	1..添加寝室人员记录 OK")
			fmt.Println("	得分：10")
			fmt.Println("---------------------------------------")
			fmt.Println("")
			tool.Increase(apiAddr, client)
		} else {
			if len(nameZuoye) >= 50 {
				nameZuoye = nameZuoye[:50]
				nameZuoye += "\n.........."
			}
			fmt.Printf("	1.添加寝室人员记录 err:返回了错误字段\n	期望的结果是:	ok//添加成功//插入成功\n	你返回的结果是：%v\n", nameZuoye)
			fmt.Println("	得分：0")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		}
		homework.Homework += nameZuoye + "-----"
	}

	time.Sleep(time.Second)
	//2.修改寝室人员记录
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/v1/person/update?name="+
		tool.First_classmate+"&sex="+"女&age=100", nil)
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += (" 修改寝室人员接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 接口访问失败！")

	} else {
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		//返回的数据是切片字节，转成字符串进行判断
		nameZuoye := string(body)

		//判断返回的字段是否修改过
		if strings.Contains(nameZuoye, "女") && strings.Contains(nameZuoye, "100") &&
			strings.Contains(nameZuoye, "小明") && strings.Contains(nameZuoye, "重庆三峡职业学院") {
			homework.Score += 10
			fmt.Println("	2..修改寝室人员记录 OK")
			fmt.Println("	得分：10")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		} else {
			if len(nameZuoye) >= 50 {
				nameZuoye = nameZuoye[:50]
				nameZuoye += "\n.........."
			}
			fmt.Printf("	2.修改寝室人员记录 err:返回了错误字段\n	期望的结果是:	小明	女	100	重庆三峡职业学院\n	你返回的结果是：\n%v\n", nameZuoye)
			fmt.Println("	得分：0")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		}

		homework.Homework += nameZuoye + "-----"

	}

	time.Sleep(time.Second)
	//3.查询寝室人员记录
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/v1/person/query", nil)
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += (" 查询寝室人员接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 接口访问失败！")

	} else {
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		//返回的数据是切片字节，转成字符串进行判断
		nameZuoye := string(body)
		if strings.Contains(nameZuoye, "小明") && strings.Contains(nameZuoye, "小周") &&
			strings.Contains(nameZuoye, "小张") {
			homework.Score += 20
			fmt.Println("	3..查询寝室人员记录 OK")
			fmt.Println("	得分：20")
			fmt.Println("---------------------------------------")
			fmt.Println("")
		} else {
			if len(nameZuoye) >= 50 {
				nameZuoye = nameZuoye[:50]
				nameZuoye += "\n.........."
			}
			fmt.Printf("	3.查询寝室人员记录 err:返回了错误字段\n	期望的结果是:	小明	女	100	重庆三峡职业学院 ........\n	你返回的结果是：\n%v\n", nameZuoye)
			fmt.Println("	得分：0")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		}
		homework.Homework += nameZuoye + "-----"

	}
	time.Sleep(time.Second)

	//4.添加出资记录 返回对应的想对应的值
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/v1/chuzi/add?name="+tool.First_classmate+"&goout="+tool.First_money+
		"&recording="+tool.First_reason, nil)
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += (" 添加出资记录接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 接口访问失败！")

	} else { //返回的结果必须包含添加的字段 列如：http://localhost/money/add?name=小明&goout=30&recording=买水果
		//返回 小明 30 买水果
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		//返回的数据是切片字节，转成字符串进行判断
		nameZuoye := string(body)
		//判断返回的字段是否包含添加的字段
		if strings.Contains(nameZuoye, tool.First_classmate) &&
			strings.Contains(nameZuoye, tool.First_money) &&
			strings.Contains(nameZuoye, tool.First_reason) {
			homework.Score += 20
			fmt.Println("	4.添加出资记录 OK")
			fmt.Println("	得分：20")
			fmt.Println("---------------------------------------")
			fmt.Println("")
			//这里表示能正确的添加记录
			//调用方法在添加几条记录
			tool.Increase01(apiAddr, client)
		} else { //返回的字段不包含就显示失败！
			if len(nameZuoye) >= 50 {
				nameZuoye = nameZuoye[:50]
				nameZuoye += "\n.........."
			}
			fmt.Printf("	4.添加出资记录 err:返回了错误字段\n	期望的结果是:	%v	%v	%v\n	你返回的结果是：\n%v\n",
				tool.First_classmate, tool.First_money, tool.First_reason, nameZuoye)
			fmt.Println("	得分：0")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		}
		homework.Homework += nameZuoye + "-----"
	}

	//5.查询自己出资记录
	time.Sleep(time.Second)
	//4.添加出资记录 返回对应的想对应的值
	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/v1/chuzi/query?name="+tool.Second_classmate, nil)
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += (" 查询出资记录接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 接口访问失败！")

	} else { //返回的结果必须包含添加的字段 列如：http://localhost/money/add?name=小明&goout=30&recording=买水果
		//返回 小明 30 买水果
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		//返回的数据是切片字节，转成字符串进行判断
		nameZuoye := string(body)
		//判断返回的字段是否包含添加的字段
		if strings.Contains(nameZuoye, tool.Second_classmate) &&
			strings.Contains(nameZuoye, tool.Second_money) &&
			strings.Contains(nameZuoye, tool.Second_reason) &&
			strings.Contains(nameZuoye, tool.There_reason) &&
			strings.Contains(nameZuoye, tool.There_money) {
			homework.Score += 20
			fmt.Println("	5.查询自己出资记录 OK")
			fmt.Println("	得分：20")
			fmt.Println("---------------------------------------")
			fmt.Println("")
		} else { //返回的字段不包含就显示失败！
			if len(nameZuoye) >= 50 {
				nameZuoye = nameZuoye[:50]
				nameZuoye += "\n.........."
			}
			fmt.Printf("	5.查询自己出资记录 err:返回了错误字段\n	期望的结果是:	%v	%v	%v .......\n	你返回的结果是：\n%v\n",
				tool.Second_classmate, tool.Second_money, tool.Second_reason, nameZuoye)
			fmt.Println("	得分：0")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		}
		homework.Homework += nameZuoye + "-----"
	}

	//6.显示每个人退补记录
	time.Sleep(time.Second)

	req, _ = http.NewRequest("GET", "http://"+apiAddr+"/v1/tuibu/result", nil)
	resp, err = client.Do(req)
	if err != nil {
		homework.Homework += (" 查询退补记录接口访问失败,错误是:" + err.Error())
		return fmt.Errorf(" 接口访问失败！")

	} else {
		//统计返回的字段值是否正确
		//接受返回来的参数
		body, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			homework.Homework += (" 数据接收失败,错误是:" + err.Error())
		}
		//返回的数据是切片字节，转成字符串进行判断
		nameZuoye := string(body)
		static := tool.Statistics{}
		//将字符串转化为以换行符结尾为一组数据
		lines := strings.Split(nameZuoye, "\n")
		for _, line := range lines {
			//当这一行有30这个特定数时，就说明第一个同学的值已返回
			if strings.Contains(line, "30") {
				static.First_number++
			}
			//当这一行有90这个特定数时，就说明第二个同学的值已返回
			if strings.Contains(line, "90") {
				static.Second_number++
			}
			//当这一行有60这个特定数时，就说明第三个同学的值已返回

			if strings.Contains(line, "60") {
				static.There_number++
			}
		}
		//这里进行判断对应的值是否正确
		if static.First_number == 1 && static.Second_number == 1 && static.There_number == 1 {

			homework.Score += 20
			fmt.Println("	6.查询退补记录 OK")
			fmt.Println("	得分：20")
			fmt.Println("---------------------------------------")
			fmt.Println("")

		} else {
			if len(nameZuoye) >= 50 {
				nameZuoye = nameZuoye[:50]
				nameZuoye += "\n.........."
			}
			fmt.Printf("	6.查询退补记录 err:返回了错误字段\n	期望的结果是:	%v	%v	%v ........\n	你返回的结果是：%v\n",
				tool.First_classmate, tool.First_money, "0", nameZuoye)
			fmt.Println("	得分：0")
			fmt.Println("---------------------------------------")
			fmt.Println("")
		}

		homework.Homework += nameZuoye + "-----"
	}
	return nil
}
